package com.darren.euc.util.light;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.darren.euc.util.light.dto.GateWayDTO;
import com.darren.euc.util.light.pojo.GateWayAllDevicePojo;
import com.darren.euc.util.light.pojo.LightControlMsgPOJO;
import com.darren.euc.util.light.pojo.Msg;
import com.darren.euc.util.light.utils.HttpRequest;
import com.darren.euc.util.light.utils.RSAUtils;
import org.apache.commons.lang.StringUtils;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.security.Key;
import java.security.interfaces.RSAPublicKey;
import java.util.Base64;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

/**
 * 灯光控制
 * Created by hanji on 2018/3/14.
 */
public class LightUtils {
    //登录相关
    private static String SECURE_URL = "http://server.atsmartlife.com/secureport";
    //设备相关
    private static String GET_POSTMSG = "http://server.atsmartlife.com/postmsg";
    //获取消息
    private static String GET_MSG = "http://server.atsmartlife.com/getmsg";
    //电话
    //private static final String MOBILE = "13380872836";
    private static final String PASSWORD = "123456";
    //获取动态密码
    private static String DYNAMIC_PASS_JSON = "{\"cmd\":\"get_dynamic_passwd\",\"time\":\"TIME\"}";
    //登录
    private static String LOGIN_JSON = "{\"cmd\":\"login\",\"from_username\":\"FROM_USERNAME\",\"password\":\"PASSWORD\"}";
    //获取网关列表
    private static String ALL_GATEWAY_JSON = "{\"cmd\":\"get_allfriend\",\"token\":\"TOKEN\",\"offset\":\"0\",\"total\":\" 10\"}";
    //公钥
    private static final String PUBLIC_KEY =    "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA54dIlq44FJP1WaWpUF1Z" +
									            "I60W8mcZnK0ADr+dKe+bnjcjdztjjzeFzCQJGbDnfUzMrDXkep6SENNNVlZ7pl5V" +
									            "bJOfaZHKiuD1mvrSQv8TybfixRmnBuJtEA6jKV1oKLnViR0vGQI2ty+1U04xRQcS" +
									            "SZ+W+Y6ZnMwZLV6jBQsfPMmTUH4cCv6Nk98q3cT1h1xFA4+JMh9XmhG/bUWGKZIx" +
									            "AQBJPbWWMnixZGlmNv9G67qP8QWy0vKbm+J7JYKayjDZXbss68+MHzjg6z5lcK4G" +
									            "5NQ9+/2F6T5QQ8Qo5r9gBO0r/y1AZRC2jNWC7DyaVc85FxsTSmiqFOJYI2EIp76o" +
									            "bwIDAQAB";
    //AES类型
    private static final String AESTYPE ="AES/ECB/NoPadding";

    //等待4s后重试
    private static final int TRYSECONDS = 4000;

    //手机号hashtable
    private static Hashtable<String,Integer> mobileControlTable = new Hashtable<>(128);

    //初始化手机号 0 未用 1 正在使用
    static {
        mobileControlTable.put("13522931134",0);
        mobileControlTable.put("15652310671",0);
        mobileControlTable.put("18518216282",0);
        mobileControlTable.put("15210304637",0);
        mobileControlTable.put("13811193828",0);
        mobileControlTable.put("18911911671",0);
        mobileControlTable.put("18501970673",0);
        mobileControlTable.put("18500199466",0);
        mobileControlTable.put("18811028692",0);
        mobileControlTable.put("18531686267",0);
        mobileControlTable.put("18211068718",0);

    }

    public static void main(String []args) throws Exception {

//        String token = getToken("13581660468","123456");
//        System.out.println(token);
        //传入 网关的名称 设备名称  房间   on/off
        //boolean flag = controlLight("zg_bjdcq_pujikeji_aqhvo_s2a2b2u20f1r1n1_g","吊灯","客厅","13380872836","123456","off");
        //根据网关查询所有设备的状态信息，返回json字符串
        String to_username = "cn_gdsz_aitezhinengauto_s1a1b1u1f17r40n1_g";
//        String state_json = getGateWayDeviceList(to_username,"13581660468","86037567");
//        System.out.print(state_json);



        boolean flag = controlLight(to_username,"C-17吊灯","C-17","13380872836","123456","off");

        Thread.sleep(2000);

        flag = controlLight(to_username,"C-17吊灯","C-17","13380872836","123456","on");


    }

    /**
     * 获取空闲手机号
     * @return
     */
    private static String getFreeMobile(){
        String mobile = "";
        int tryLength = 0;
        //如果没有空闲的手机号就等待4s
        while(tryLength < 2) {
            for (Map.Entry<String, Integer> map : mobileControlTable.entrySet()) {
                if (map.getValue() == 0) {
                    mobile = map.getKey();
                    mobileControlTable.put(mobile, 1);
                    break;
                }
            }
            if(StringUtils.isEmpty(mobile)){
                try {
                    Thread.sleep(TRYSECONDS);
                } catch (InterruptedException e) {
                }
                tryLength ++;
            }else{
                tryLength = 8;
            }
        }
        return mobile;
    }

    /**
     * 1.开启/关闭控制灯
     * @param to_username 网关名 eg:  zg_bjdcq_pujikeji_aqhvo_s2a2b2u20f1r1n1_g
     * @param device_name 设备名称 eg: 吊灯
     * @param room_name 房间名称 eg: 客厅
     * @param mobile 操作灯的手机号码 eg: 13380872836
     * @param passowrd 密码  eg: 123456
     * @param on_off 开启或关闭  eg: on 开 off 关
     * @return
     * @throws IOException
     */
    public static boolean controlLight(String to_username,String device_name,String room_name,String mobile,String passowrd,String on_off) throws Exception {
        mobile = getFreeMobile();
        passowrd = PASSWORD;
        System.out.println(mobile);
        try {
            String token = getToken(mobile,passowrd);
            String dynamic_passwd = getDynamicPassDes("dynamic_passwd");
            GateWayAllDevicePojo gateWayAllDevicePojo = new GateWayAllDevicePojo();
            gateWayAllDevicePojo.setCmd("send_msg");
            gateWayAllDevicePojo.setTo_username(to_username);
            gateWayAllDevicePojo.setSubject("control");
            gateWayAllDevicePojo.setToken(token);
            LightControlMsgPOJO msg = new LightControlMsgPOJO();
            msg.setFrom_role("phone");
            msg.setMsg_type("device_control");
            msg.setCommand("control");
            msg.setFrom_account(mobile);
            msg.setDevice_name(device_name);
            msg.setRoom_name(room_name);
            Map<String, Integer> map = new HashMap<String, Integer>();
            map.put("value", 0);
            msg.setFunc_value(map);
            msg.setFunc_command(on_off);
            gateWayAllDevicePojo.setMsg(msg);
            String result = HttpRequest.sendPostRaw(GET_POSTMSG, AES_Encrypt(JSON.toJSONString(gateWayAllDevicePojo), dynamic_passwd), "");

            String getMsgJson = HttpRequest.sendGet(GET_MSG, "token=" + token);
            System.out.println(getMsgJson);
            if("".equals(getMsgJson)){
                return false;
            }
            String getMsg = AES_Decrypt(getMsgJson.trim(), dynamic_passwd);
            System.out.println(getMsg);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }finally {
            mobileControlTable.put(mobile,0);
        }
        return true;
    }

    /**
     *  2.根据网关名称获取旗下所有设备的状态
     *  返回的是json字符串，自己解析
     * @param friend 网关名 eg:  zg_bjdcq_pujikeji_aqhvo_s2a2b2u20f1r1n1_g
     * @return
     * @throws IOException
     */
    public static String getGateWayDeviceList(String friend,String mobile,String password) throws Exception {
        mobile = getFreeMobile();
        password = PASSWORD;
        System.out.print(mobile+"   "+password);
        try {
            String token = getToken(mobile,password);
            String dynamic_passwd = getDynamicPassDes("dynamic_passwd");
            GateWayAllDevicePojo gateWayAllDevicePojo = new GateWayAllDevicePojo();
            gateWayAllDevicePojo.setCmd("send_msg");
            gateWayAllDevicePojo.setTo_username(friend);
            gateWayAllDevicePojo.setSubject("control");
            gateWayAllDevicePojo.setToken(token);
            Msg msg = new Msg();
            msg.setFrom_role("phone");
            msg.setMsg_type("device_manager");
            msg.setCommand("query");
            msg.setFrom_account(friend);
            gateWayAllDevicePojo.setMsg(msg);
            String result = HttpRequest.sendPostRaw(GET_POSTMSG, AES_Encrypt(JSON.toJSONString(gateWayAllDevicePojo), dynamic_passwd), "");
            String result_json = AES_Decrypt(result.trim(), dynamic_passwd);

            String getMsgJson = HttpRequest.sendGet(GET_MSG, "token=" + token);
            String getMsg = AES_Decrypt(getMsgJson.trim(), dynamic_passwd);

            JSONObject jsonObject = JSON.parseObject(getMsg.trim());
            //如果获取到的数据是上报的数据，递归调用
            if(jsonObject.getString("cmd").equals("dev_report")){
                return getGateWayDeviceList(friend,mobile,password);
            }
            return jsonObject.getString("msg");
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            mobileControlTable.put(mobile,0);
        }
        return null;
    }


    /**
     * 3.获取网关列表
     * @return
     * @throws IOException
     */
    private static GateWayDTO getGateWayList(String token, String dynamic_passwd) throws IOException {
        ALL_GATEWAY_JSON = ALL_GATEWAY_JSON.replaceAll("TOKEN",token);
        String result = HttpRequest.sendPostRaw(GET_POSTMSG,AES_Encrypt(ALL_GATEWAY_JSON,dynamic_passwd),"");
        String result_json = AES_Decrypt(result,dynamic_passwd);
        GateWayDTO gateWayDTO = JSON.parseObject(result_json.trim(), new TypeReference<GateWayDTO>() {});
        return gateWayDTO;
    }

    /**
     * 1.获取动态的passwd
     * @return
     * @throws IOException
     */
    private static String getDynamicPassDes(String token) throws IOException {
        DYNAMIC_PASS_JSON = DYNAMIC_PASS_JSON.replaceAll("TIME",System.currentTimeMillis()*1000+"");
        String result = HttpRequest.sendPostRaw(SECURE_URL,encrypt(DYNAMIC_PASS_JSON),"");
        String dynamic_pass_json = decrypt(result);
        JSONObject dynamic_pass_json_object = JSON.parseObject(dynamic_pass_json);
        String dynamic_pass = dynamic_pass_json_object.getString("dynamic_passwd");
        return dynamic_pass;
    }

    /**
     * 2.获取登录的token
     * @return
     * @throws IOException
     */
    private static String getToken(String mobile,String password) throws IOException {
        //登录获取token
        LOGIN_JSON = LOGIN_JSON.replaceAll("FROM_USERNAME",mobile).replaceAll("PASSWORD",password);
        String token = getJSONStrKey(SECURE_URL,LOGIN_JSON,"token");
        return token;
    }

    /**
     * 给json获取key的value值
     * @param key
     * @return
     */
    private static String getJSONStrKey(String url,String data,String key) throws IOException {
        String json = HttpRequest.sendPostRaw(url,encrypt(data),"");
        String token = decrypt(json);
        System.out.println("---------->>>>>>>>>>>"+token);
        JSONObject json_object = JSON.parseObject(token);
        return json_object.getString(key);
    }

    /**
     * RSA加密
     * @param plainText
     * @return
     */
    private static String encrypt(String plainText){
        Cipher cipher = null;
        byte[] cipherText = null;
        try {
            cipher = Cipher.getInstance("RSA");
            RSAPublicKey pubKey = generateKey();
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            cipherText = cipher.doFinal(plainText.getBytes());
            //加密后的东西
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new String(Base64.getEncoder().encode(cipherText));
    }

    /**
     * RSA解密
     * @param plainText
     * @return
     */
    private static String decrypt(String plainText){
        return RSAUtils.publicDecrypt(plainText,generateKey());
    }

    private static RSAPublicKey generateKey() {
        try {
            RSAPublicKey pubKey = RSAUtils.getPublicKey(PUBLIC_KEY);
            return pubKey;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    /**
     * AES加密
     * @param plainText
     * @param keyStr
     * @return
     */
    private static String AES_Encrypt(String plainText,String keyStr) {
        byte[] encrypt = null;
        try{
            Key key = generateKey(keyStr);
            Cipher cipher = Cipher.getInstance(AESTYPE);
            cipher.init(Cipher.ENCRYPT_MODE, key);
            int pad=plainText.getBytes().length%16;
            if(pad!=0)
            {
                for(int i=0;i<16-pad;i++)
                {
                    plainText=plainText+"\0";
                }
            }
            byte c[]=plainText.getBytes();
            encrypt = cipher.doFinal(plainText.getBytes());
        }catch(Exception e){
            e.printStackTrace();
        }
        return new String(Base64.getEncoder().encode(encrypt));
    }

    /**
     * AES解密
     * @param content
     * @param password
     * @return
     */
    private static String AES_Decrypt(String content, String password) {

        try {
            //实例化
            Cipher cipher = Cipher.getInstance(AESTYPE);

            //使用密钥初始化，设置为解密模式
            cipher.init(Cipher.DECRYPT_MODE, generateKey(password));

            //执行操作
            byte[] result = cipher.doFinal(Base64.getDecoder().decode(content.getBytes()));

            return new String(result, "utf-8");
        } catch (Exception ex) {
        }

        return null;
    }

    private static Key generateKey(String key)throws Exception{
        try{
            SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
            return keySpec;
        }catch(Exception e){
            e.printStackTrace();
            throw e;
        }
    }
}
